home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / gslp.ps < prev    next >
Text File  |  1997-11-17  |  16KB  |  538 lines

  1. %    Copyright (C) 1991, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % gslp.ps - format and print text
  16.  
  17. % This utility provides functionality approximately equivalent to the Unix
  18. % `enscript' program.  It prints plain text files using a single font.
  19. % It currently handles tabs and formfeeds, but not backspaces.
  20. % It only works with fixed-pitch fonts.
  21. % Standard flags implemented:
  22. %    -12BclqRr -b<header> -f<font> -F<hfont> -L<lines> -p<outfile>
  23. % Sun flags implemented:
  24. %    -T<n>    set tab width
  25. % Flags ignored:
  26. %    -GghKkmow -# -C -d -J -n -P -S -s -t -v
  27. % Flags added:
  28. %    --columns <n>
  29. %        print in <n> columns
  30. %    --detect
  31. %        treat the file as PostScript if it starts with %!
  32. %    --first-page <n>
  33. %        start printing at page <n>
  34. %    --last-page <n>
  35. %        stop printing after page <n>
  36. %    --(heading|footing)-(left|center|right) <string>
  37. %        set the heading/footing fields; use -B first to clear
  38. %    --margin-(top|bottom|left|right) <inches>
  39. %        set a margin
  40. %    --no-eject-(file|formfeed)
  41. %        end-of-file/FF only starts a new column, not a new sheet
  42. %    --spacing <n>
  43. %        use double (n=2), triple (n=3), etc. spacing
  44. % Also, the string %# in a heading or footing is replaced with the page #.
  45. /PageNumberString (%#) def
  46.  
  47. /lpdict 150 dict def
  48. lpdict begin
  49.  
  50. % build iso-latin-1 version of a font
  51. /font-to-iso-latin-1 {    % <font> font-to-iso-latin-1 <font>
  52.     %% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
  53.     dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
  54.     /Encoding ISOLatin1Encoding def currentdict end
  55.     dup /FontName get 80 string cvs (-ISOLatin1) concatstrings cvn 
  56.     exch definefont
  57. } def
  58.  
  59. /find-latin-font {    % <name> find-latin-font <font>
  60.   findfont font-to-iso-latin-1
  61. } def
  62.  
  63. % Define the initial values of the printing parameters.
  64.  
  65. /BodyFont null def        % use default
  66.   /defaultBodyFont
  67.     { /Courier find-latin-font Landscape { 7 } { 10 } ifelse scalefont } def
  68. /Columns 1 def
  69. /DetectFileType false def
  70. /EjectEOF true def
  71. /EjectFF true def
  72. /Footers false def
  73. /FootingLeft () def
  74. /FootingCenter () def
  75. /FootingRight () def
  76. /Headers true def
  77. /HeadingLeft () def
  78. /HeadingCenter () def
  79. /HeadingRight (page ) PageNumberString concatstrings def
  80. /HeadingFont null def        % use default
  81.   /defaultHeadingFont
  82.     { /Courier-Bold find-latin-font 10 scalefont } def
  83. /Landscape false def
  84. /MarginBottom 36 def        % 1/2"
  85. /MarginLeft 36 def        % 1/2"
  86. /MarginRight 36 def        % 1/2"
  87. /MarginTop 36 def        % 1/2"
  88. /MaxLines 9999 def        % max lines per page
  89. /Noisy true def            % i.e., not quiet
  90. /OutFile null def        % null = write directly to device
  91. /PageFirst 1 def
  92. /PageLast 99999 def
  93. /Spacing 1 def
  94. /Tab 8 def
  95. /Truncate false def        % wrap long lines, don't truncate
  96.  
  97. % When writing to a file, we want to write out PostScript;
  98. % when writing to the printer, we want to execute it;
  99. % some commands should be executed regardless.
  100. % lpexec provides for all this.
  101.  
  102. /lpexec        % <arg1> ... <argn> </op> <n> <do_always> lpexec -
  103.  { OutFile null eq
  104.     { pop 1 add true
  105.     }
  106.     { /t exch def 1 add /n exch def cvx
  107.       n { n -1 roll dup wosp } repeat
  108.       OutFile (\n) writestring
  109.       n t
  110.     }
  111.    ifelse
  112.     { pop load exec }
  113.     { { pop } repeat }
  114.    ifelse
  115.  } def
  116.  
  117. /lpmoveto
  118.  { /moveto 2 true lpexec
  119.  } def
  120. /lpshow
  121.  { dup length 0 ne { /show 1 true lpexec } { pop } ifelse
  122.  } def
  123. /lpsetmyfont
  124.  { dup load setfont
  125.    OutFile null ne { cvx /setfont 1 false lpexec } { pop } ifelse
  126.  } def
  127.  
  128. % Define some utility procedures.
  129.  
  130. /banner        % ypos left center right
  131.  { /HFont lpsetmyfont
  132.    3 -1 roll bannerstring pop 0 4 index pwidth showline2 pop
  133.    exch bannerstring pwidth exch sub 2 div 3 index pwidth showline2 pop
  134.    bannerstring
  135.         % Prevent the last character of the heading from grazing
  136.         % the right margin.
  137.         % ****** WHY DOES IT REQUIRE SO MUCH PADDING? ******
  138.    ( ) stringwidth pop 2 mul add
  139.    pwidth exch sub
  140.    3 -1 roll pwidth showline2 pop
  141.  } def
  142.  
  143. /bannerstring    % string -> string width
  144.   { PageNumberString search
  145.      { exch pop pindex 4 string cvs concatstrings exch concatstrings
  146.      }
  147.     if dup stringwidth pop
  148.   } def
  149.  
  150. /beginpage
  151.  { /lindex 0 def
  152.    /skipping pindex PageFirst ge pindex PageLast le and not def
  153.    /save 0 true lpexec /pagesave exch def
  154.    skipping { nulldevice   /OutFile null def } if
  155.    Headers
  156.     { lheight hdescent add
  157.       HeadingLeft HeadingCenter HeadingRight banner
  158.     } if
  159.    /BFont lpsetmyfont
  160.  } def
  161.  
  162. /endpage
  163.  { lindex 0 ne
  164.     { Footers
  165.        { topskip plength sub hdescent add
  166.          FootingLeft FootingCenter FootingRight banner
  167.        } if
  168.       /showpage 0 false lpexec
  169.     } if
  170.    pagesave /restore 0 true lpexec
  171.    /pindex pindex 1 add def
  172.  } def
  173.  
  174. /endcolumn
  175.  { lindex colines 1 sub add colines idiv colines mul
  176.    dup llength ge { pop endpage beginpage } { /lindex exch def } ifelse
  177.  } def
  178.  
  179. /fontheight    % <font> fontheight <ascent> <height>
  180.  { gsave setfont
  181.    newpath 0 0 moveto
  182.    (|^_j) false charpath
  183.    pathbbox exch pop dup 2 index sub 4 -2 roll pop pop
  184.    grestore exch 1.25 mul exch 1.25 mul
  185.  } def
  186.  
  187. /wosp
  188.  { OutFile ( ) writestring OutFile exch write==only
  189.  } def
  190.  
  191. /outfont        % name font ->
  192.  { OutFile null ne
  193.     { exch wosp
  194.       dup /FontName get 
  195.       dup wosp OutFile ( findfont) writestring
  196.       %% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
  197.       OutFile ( 
  198.     dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
  199.     /Encoding ISOLatin1Encoding def currentdict end
  200.       ) writestring
  201.       wosp OutFile (-ISOLatin1 exch definefont) writestring
  202.       /FontMatrix get 0 get 1000 mul round cvi wosp
  203.       OutFile ( scalefont def\n) writestring
  204.     }
  205.     { pop pop
  206.     }
  207.    ifelse
  208.  } def
  209.  
  210. /StringFF (\f) def
  211. /CharFF StringFF 0 get def
  212. /StringTAB (\t) def
  213. /CharTAB StringTAB 0 get def
  214.  
  215. /showline        % line -> leftover_line (handles \f)
  216.  {  { showline1 dup length 0 eq { exit } if
  217.       dup 0 get CharFF ne { exit } if
  218.       EjectFF { endpage beginpage } { endcolumn } ifelse
  219.       skip1
  220.     }
  221.    loop
  222.  } def
  223.  
  224. /showline1        % line -> leftover_line (handles page break)
  225.  { lindex llength eq { endpage beginpage } if
  226.    lindex colines idiv cowidth mul        % x
  227.    lindex colines mod 1 add lheight mul neg fascent sub    % y
  228.    1 index cowidth add
  229.    showline2
  230.    /lindex lindex 1 add def
  231.  } def
  232.  
  233. /showline2    % string x y xlimit -> leftover_string (handles tabs)
  234.  { 2 index exch 5 2 roll lpmoveto    % xinit xlimit string
  235.     { showline3 dup length 0 eq { exit } if
  236.       dup 0 get CharTAB ne { exit } if
  237.       currentpoint exch 4 index sub tabwx div
  238.     0.05 add ceiling tabwx mul 4 index add exch lpmoveto
  239.       skip1
  240.       currentpoint pop 2 index ge { exit } if
  241.     }
  242.    loop exch pop exch pop
  243.  } def
  244.  
  245. /showline3    % xlimit string -> xlimit leftover_string
  246.         % (finds line break / tab / formfeed)
  247.  { currentpoint pop 2 index exch sub
  248.      cwx div 0.1 add cvi 0 max 1 index length min
  249.    1 index 0 3 -1 roll getinterval
  250.     % look for \f or \t
  251.    StringFF search { exch pop exch pop } if
  252.    StringTAB search { exch pop exch pop } if
  253.    dup lpshow
  254.    length dup 2 index length exch sub getinterval
  255.  } def
  256.  
  257. /skip1
  258.  { dup length 1 sub 1 exch getinterval
  259.  } def
  260.  
  261. /e== {        % <object> e== - -- print an object to stderr
  262.   (%stderr) (w) file dup 3 -1 roll write==only flushfile
  263. } def
  264.  
  265. /eprint {    % <string> eprint - -- print a string to stderr
  266.   (%stderr) (w) file dup 3 -1 roll writestring flushfile
  267. } def
  268.  
  269. % The main printing procedure
  270.  
  271. /lp        % file initial_chars ->
  272.  { /lpline exch def
  273.    /lpfile exch def
  274.    /save 0 true lpexec
  275.  
  276. % Initialize the device and fonts.
  277.    /BFont
  278.      BodyFont null eq { defaultBodyFont } { BodyFont } ifelse def
  279.    /BFont BFont outfont
  280.    Headers Footers or
  281.     { /HFont
  282.     HeadingFont null eq { defaultHeadingFont } { HeadingFont } ifelse def
  283.       /HFont HFont outfont
  284.     }
  285.    if
  286.  
  287. % Get the layout parameters.
  288.    clippath
  289.    Landscape { 90 /rotate 1 true lpexec } if
  290.    BFont setfont ( ) stringwidth pop /cwx exch def
  291.      cwx Tab mul /tabwx exch def
  292.    BFont fontheight /fheight exch def /fascent exch def
  293.    Headers Footers or { HFont fontheight } { 0 0 } ifelse
  294.      /hheight exch def /hascent exch def
  295.      /hdescent hheight hascent sub def
  296.    fheight Spacing mul /lheight exch def
  297.    Headers { hheight lheight add } { 0 } ifelse
  298.      /topskip exch def
  299.    Footers { hheight lheight add } { 0 } ifelse
  300.      /botskip exch def
  301.    /pskip topskip botskip add def
  302.     % Translate the page so that (0,0) corresponds to
  303.     % the top of the topmost body line.
  304.    pathbbox
  305.      2 index sub MarginBottom MarginTop add sub /plength exch def
  306.      2 index sub MarginLeft MarginRight add sub /pwidth exch def
  307.      pwidth Columns div /cowidth exch def
  308.      exch MarginLeft add
  309.      exch MarginBottom add plength add topskip sub
  310.      /translate 2 true lpexec
  311.    plength pskip sub lheight div cvi MaxLines min
  312.      dup /colines exch def
  313.      Columns mul /llength exch def
  314.    OutFile null ne { nulldevice } if
  315.  
  316. % Print layout
  317.    Noisy
  318.     { (Page height = ) eprint llength e==
  319.       (.\n) eprint flush
  320.     } if
  321.  
  322. % Disable stack recording so we can use stopped with readline.
  323.    $error /recordstacks false put
  324.  
  325. % Initialize for the first page.
  326.    /lbuf 1000 string def
  327.    /pindex 1 def
  328.    beginpage
  329.  
  330. % Iterate through the file.
  331.    lpline
  332.     { dup length /pos exch def
  333.       lbuf exch 0 exch putinterval
  334.        { lpfile lbuf pos lbuf length pos sub getinterval readline } stopped
  335.        {    % Filled the line before a CR or EOF.
  336.          exch pop showline
  337.        }
  338.        {    % Reached CR and/or EOF first.
  339.          exch length pos add lbuf exch 0 exch getinterval
  340.      1 index { showline } if        % omit final empty line
  341.       { dup length 0 eq Truncate or { pop () exit } if
  342.         showline
  343.       }
  344.      loop
  345.      exch not { exit } if
  346.        }
  347.       ifelse
  348.     } loop
  349.    pop
  350.  
  351. % Wrap up.
  352. %**************** WHY IS THIS COMMENTED OUT? ****************
  353. %   EjectEOF { endpage } { endcolumn } ifelse
  354.    endpage
  355.    /restore 0 true lpexec
  356.  
  357.  } def
  358.  
  359. end
  360.  
  361. % Usage: <file> lp
  362. %   prints <file> using the current parameter settings.
  363. % Usage: [ <arg1> ... <argn> ] lpcommand
  364. %   interprets args like a command line.
  365.  
  366. /lp { save   lpdict begin () lp end   restore } def
  367.  
  368. lpdict begin
  369.  
  370. /splitfn        % (FontNNN) -> <font>
  371.  { dup /arg exch def length
  372.     { dup 0 le { exit } if
  373.       dup 1 sub arg exch get dup 48 ge exch 59 le and not { exit } if
  374.       1 sub
  375.     } loop
  376.    arg exch 0 exch getinterval dup cvn find-latin-font
  377.    exch arg exch anchorsearch pop pop cvr scalefont
  378.  } def
  379.  
  380. % Parse the command line switches.
  381.  
  382. /doswitch    % argn ... arg1 (-?) restofswitch ->
  383.  { exch dup cvn lpdict exch known
  384.     { cvn load exec }
  385.     { exch pop (Unknown switch: ) eprint eprint (\n) eprint }
  386.    ifelse
  387.  } def
  388.  
  389. /more        % argn ... arg1 restofswitch ->
  390.  { dup length 0 ne
  391.     { (- ) dup 1 3 index 0 get put
  392.       exch dup length 1 sub 1 exch getinterval
  393.       doswitch
  394.     }
  395.     { pop
  396.     }
  397.    ifelse
  398.  } def
  399.  
  400. /-- { (--) exch concatstrings
  401.       dup cvn lpdict exch known
  402.        { cvn load exec }
  403.        { (Unknown switch: ) eprint eprint (\n) eprint }
  404.       ifelse
  405.     } def
  406. /--columns { cvi 1 max /Columns exch def } def
  407. /--detect { /DetectFileType true def } def
  408. /--first-page { cvi /PageFirst exch def } def
  409. /--footing-center { /FootingCenter exch def   /Footers true def } def
  410. /--footing-left { /FootingLeft exch def   /Footers true def } def
  411. /--footing-right { /FootingRight exch def   /Footers true def} def
  412. /--heading-center { /HeadingCenter exch def   /Headers true def } def
  413. /--heading-left { /HeadingLeft exch def   /Headers true def } def
  414. /--heading-right { /HeadingRight exch def   /Headers true def } def
  415. /--last-page { cvi /PageLast exch def } def
  416. /--margin-bottom { cvr 72.0 mul /MarginBottom exch def } def
  417. /--margin-left { cvr 72.0 mul /MarginLeft exch def } def
  418. /--margin-right { cvr 72.0 mul /MarginRight exch def } def
  419. /--margin-top { cvr 72.0 mul /MarginTop exch def } def
  420. /--no-eject-file { /EjectEOF false def } def
  421. /--no-eject-formfeed { /EjectFF false def } def
  422. /--spacing { cvr /Spacing exch def } def
  423.  
  424. /-# { pop } def        % ignore
  425. /-+ { -- } def
  426. (-1)cvn { /Columns 1 def   more } def
  427. (-2)cvn { /Columns 2 def   more } def
  428. /-b { /HeadingLeft exch def   /HeadingCenter () def   /HeadingRight PageNumberString def
  429.       /Headers true def
  430.       /break true def
  431.     } def
  432. /-B { /HeadingLeft () def   /HeadingCenter () def   /HeadingRight () def
  433.       /Headers false def
  434.       /FootingLeft () def   /FootingCenter () def   /FootingRight () def
  435.       /Footers false def
  436.       /break true def
  437.       more
  438.     } def
  439. /-C { pop } def        % ignore
  440. /-c { /Truncate true def   more } def
  441. /-d { pop } def        % ignore
  442. /-f { splitfn /BodyFont exch def } def
  443. /-F { splitfn /HeadingFont exch def } def
  444. /-G { more } def    % ignore
  445. /-g { more } def    % ignore
  446. /-h { more } def    % ignore
  447. /-J { pop } def        % ignore
  448. /-K { more } def    % ignore
  449. /-k { more } def    % ignore
  450. /-l { 66 -L -B } def
  451. /-L { cvi /MaxLines exch def } def
  452. /-m { more } def    % ignore
  453. /-n { pop } def        % ignore
  454. /-o { more } def    % ignore
  455. /-p { (w) file /OutFile exch def   OutFile (%!\n) writestring } def
  456. /-P { pop } def        % ignore
  457. /-q { /Noisy false def   more } def
  458. /-r { /Landscape true def   more } def
  459. /-R { /Landscape false def   more } def
  460. /-S { pop } def        % ignore
  461. /-s { pop } def        % ignore
  462. /-T { cvi /Tab exch def } def
  463. /-v { pop } def        % ignore
  464. /-w { more } def    % ignore
  465.  
  466. /lp1        % filename ->
  467.  { break not { dup /HeadingLeft exch def } if
  468.    Noisy
  469.     { (Printing ) eprint dup eprint (\n) eprint 
  470.     } if
  471.    (r) file
  472.         % If requested, check for a PostScript file.
  473.    DetectFileType
  474.     { dup 2 string readstring pop dup (%!) eq
  475.        {    % Yes, it's a PostScript file.
  476.          pop dup 80 string readline pop pop cvx exec
  477.        }
  478.        { lp
  479.        }
  480.       ifelse
  481.     }
  482.     { () lp
  483.     }
  484.    ifelse
  485.  } bind def
  486.  
  487. /lpcstring 100 string def
  488.  
  489. end
  490.  
  491. /lpcommand        % <[arg1 ... argn]> lpcommand <any_printed>
  492.  {    % Push the commands on the stack in reverse order
  493.    mark exch
  494.    dup length 1 sub -1 0 { 1 index exch get exch } for pop
  495.    lpdict begin
  496.    /any false def
  497.    /break false def
  498.     { dup mark eq { pop exit } if
  499.       dup length 2 ge { dup 0 get (-) 0 get eq } { false } ifelse
  500.        { dup 0 2 getinterval
  501.          exch dup length 2 sub 2 exch getinterval
  502.      doswitch
  503.        }
  504.        { dup  /matched false def
  505.           { /matched true def   /any true def   lp1 } lpcstring filenameforall
  506.      matched { pop } { lp1 } ifelse        % let the error happen
  507.        }
  508.       ifelse
  509.     } loop
  510.    OutFile null ne
  511.     { OutFile (%stdout) (w) file ne { OutFile closefile } if
  512.       /OutFile null def
  513.     } if
  514.    any
  515.    end
  516.  } def
  517.  
  518. [ shellarguments
  519.  { ] dup length 0 ne { lpcommand } { false } ifelse not
  520.     { (%stderr) (w) file
  521.       [ (Usage: )
  522.     /PROGNAME where { pop PROGNAME } { (gslp) } ifelse
  523.     ( [-12BclqRr] [-b<header>] [-f<font>] [-F<hfont>]\n)
  524.     (        [-L<lines>] [-p<outfile>] [-T<tabwidth>] [--columns <n>]\n)
  525.     (        [--detect] [--first-page <page#>] [--last-page <page#>]\n)
  526.     (        [--(heading|footing)-(left|right|center) <string>]\n)
  527.     (        [--margin-(top|bottom|left|right) <inches>]\n)
  528.     (        [--no-eject-(file|formfeed)] [--spacing <n>] file1 ... filen\n)
  529.       ] { 2 copy writestring pop } forall dup flushfile closefile
  530.     }
  531.    if
  532.  }
  533.  { pop }
  534. ifelse
  535.